use std::collections::HashMap;
use std::fmt::{Debug, Formatter};
use std::sync::Arc;

use async_trait::async_trait;
use mf_macro::{mf_meta, mf_plugin};
use mf_state::{error::StateResult, plugin::{Plugin, PluginMetadata, PluginSpec, PluginTrait}, state::State, transaction::Transaction, StateConfig};
use mf_state::plugin::StateField;
use mf_state::resource::Resource;
use serde::{Deserialize, Serialize};

#[derive(Deserialize,Serialize)]
pub struct DjgcState(pub HashMap<String, serde_json::Value>);
impl Resource for DjgcState {

}
pub struct  DjgcStateImpl;

impl Debug for DjgcStateImpl {
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
        write!(f, "DjgcState")
    }
}

#[async_trait]
impl StateField for DjgcStateImpl {
    type Value = DjgcState;

    async fn init(&self, config: &StateConfig, instance: &State) -> Arc<Self::Value> {
        let mut djgc_map = HashMap::new();
        djgc_map.insert("a".to_string(),"b".into());
        djgc_map.insert("c".to_string(),"b".into());
        djgc_map.insert("b".to_string(),"b".into());
        djgc_map.insert("d".to_string(),"b".into());

        Arc::from(DjgcState(djgc_map))
    }

    async fn apply(&self, tr: &Transaction, value: Arc<Self::Value>, old_state: &State, new_state: &State) -> Arc<Self::Value> {
        value
    }

    fn serialize(&self, value: &Arc<Self::Value>) -> Option<Vec<u8>> {
        match serde_json::to_string(value) {
            Ok(json) => {Some(json.into_bytes())}
            Err(_) => {None}
        }
    }

    fn deserialize(&self, data: &[u8]) -> Option<Arc<Self::Value>> {
        serde_json::from_slice(data).ok()
    }
}

async fn append_transaction(
    _trs: &[Arc<Transaction>],
    _old_state: &Arc<State>,
    _new_state: &Arc<State>,
) -> StateResult<Option<Transaction>> {
    Ok(None)
}
async fn filter_transaction(
    _tr: &Transaction,
    _state: &State,
) -> bool {
    true
}


mf_plugin!(
    plugin_djgc,
    metadata = mf_meta!(version = "1.0.0", description = "单价构成插件", author = "ModuForge Team", tags = []),
    append_transaction = append_transaction,
    filter_transaction=filter_transaction,
    state_field = DjgcStateImpl {}
);
